import time
import functools
import torch
import numpy as np
class Timer:
    """
    a with statement with the Timer class can count the time used
    """
    def __init__(self, func):
        self.func = func

    def __enter__(self):
        self.start = time.perf_counter()
        return self

    def __exit__(self, *args):
        self.end = time.perf_counter()
        self.interval = self.end - self.start
        print(f'{self.func} took {self.interval} seconds')

def clock(f):
    @functools.wraps(f)
    def clocked(*args, **kwargs):
        t0 = time.time()
        result = f(*args, **kwargs)
        elapsed = time.time() - t0
        name = f.__name__
        # if kwargs:
        #     name += '(' + ', '.join(
        #         f'{k}={v}' for k, v in sorted(kwargs.items())) + ')'
        # args_str = ', '.join(
        #     repr(arg) for arg in args
        # )
        print('[%0.8fs] %s' % (elapsed, name))
        return result
    return clocked

@clock
def crop_by_pil(img, box):
    return img.crop(box)
@clock
def crop_by_hand(img_arr, box):
    img_arr = img_arr[...,::-1]
    img_arr =  img_arr[box[1]:box[3], box[0]:box[2]] # H, w, 3
    return img_arr

def hwc2tensor(img_arr):
    img_arr = img_arr.transpose(2,0,1)
    img_arr = np.ascontiguousarray(img_arr)
    return torch.from_numpy(img_arr)
    return img_arr


class Int8ToFloat01(object):
    def __call__(self, tensor):
        # Ensure the input is a PyTorch tensor
        if not torch.is_tensor(tensor):
            raise TypeError("Input must be a PyTorch tensor.")

        # Check if the tensor is of integer type
        if not torch.is_floating_point(tensor):
            # Convert int8 tensor to float tensor in the range [0, 1]
            tensor = tensor.float() / 255.0

        return tensor

